2023/12/232479字符

Proxy 代理

Proxy 代理(中介公司)

数据更改

const obj = {
    a: 1,
    b: 2
}
const proxy = new Proxy(obj, {});
proxy.a = 10;
console.log(proxy);  //--> Proxy {a: 10, b: 2}

set重写

const obj = {
    a: 10,
    b: 20
}
const proxy = new Proxy(obj, {
    set (target, properKey, value) {
        // target[properKey] = value;  // Reflect.set 重写
        Reflect.set(target, properKey, value);  // 尽量使用底层提供的方法
    }
});
proxy.a = 100;
console.log(obj.a);  //--> 100

虚拟DOM Vue 原理

<div id='demo'></div>

function observer(target = {}) {
    const div = document.getElementById('demo');
    const proxy = new Proxy(target, {
        set(target, prop, value) {
            Reflect.set(target, prop, value);  // 没有ES6之前拿 Object.defineProperties 实现
            render();  // 重新设置后渲染
        },
        get(target, prop) {
            return Reflect.get(target, prop);
        }
    })
    render();  // 初始化渲染

    function render() {  // 渲染到页面
        let html = '';
        for (const prop of Object.keys(proxy)) {
            html += `<p><span>${prop}</span>:<span>${proxy[prop]}</span></p>`
        }
        div.innerHTML = html;
    }
    return proxy;
}
const obj = {
    a: 1,
    b: 2
}
let newObj = observer(obj);
newObj.a = 100;

函数代理

function validator(func, ...types) {
    const proxy = new Proxy(func, {
        apply(target, thisArgument, argumentsList) {
            types.forEach((val, i) => {
                const arg = argumentsList[i];
                if (typeof arg !== val) {
                    throw new TypeError(`第${i + 1}个参数${argumentsList[i]}不满足类型${val}`)
                }
            })
            return Reflect.apply(target, thisArgument, argumentsList);
        }
    })
    return proxy;
}

function sum(a, b) {
    return a + b;
}
const sumProxy = validator(sum, 'number', 'number');
console.log(sumProxy(3, 4))  //--> 7

动态属性

const add = new Proxy(
  {
    _store: 0,
  },
  {
    get(target, prop, receiver) {
      if (prop === Symbol.toPrimitive) {
        return () => target._store;
      }
      target._store += +prop;
      return receiver;
    }
  }
)

const num = add[1][2][5] + 10;
console.log(num);  //--> 18